/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package z.h.w.jar.kit.method;

import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.imageio.ImageIO;
import z.h.w.jar.kit.clazz.XML;

/**
 *
 * @author EnzoZhong
 */
public class IO {

      public static void makeImg ( String imgUrl , String fileURL ) {
            try {
                  BufferedOutputStream bufferedOutputStream;
                  URL url = new URL ( imgUrl );
                  InputStream InputStream = url.openStream ();
                  try ( BufferedInputStream bufferedInputStream = new BufferedInputStream ( InputStream ) ) {
                        int index = imgUrl.lastIndexOf ( '/' );
                        String sName = imgUrl.substring ( index + 1 , imgUrl.length () );
                        File img = new File ( fileURL + sName );
                        bufferedOutputStream = new BufferedOutputStream ( new FileOutputStream ( img ) );
                        byte[] buf = new byte[ 2048 ];
                        int length = bufferedInputStream.read ( buf );
                        while ( length != -1 ) {
                              bufferedOutputStream.write ( buf , 0 , length );
                              length = bufferedInputStream.read ( buf );
                        }
                  }
                  bufferedOutputStream.close ();
            } catch ( Exception e ) {
                  System.err.println ( e );
            }
      }

      /**
       *
       * @param in
       * @return
       */
      public static synchronized String back2Floder ( Integer in ) {
            StringBuffer sb = new StringBuffer ();
            for ( int x = 0 ; x < in ; x ++ ) {
                  sb.append ( "../" );
            }
            return sb.toString ();
      }

      public static synchronized String back2Floder ( String path ) {
            return back2Floder ( Text.count ( path , "/" ) );
      }

      public static synchronized String getExt ( String path ) {
            String[] array;
            if ( path.contains ( "." ) ) {
                  array = path.split ( "." );
                  return array[array.length - 1];
            } else {
                  return null;
            }
      }

      public static synchronized String getExt ( File file ) {
            return getExt ( file.getName () );
      }

      public static synchronized void unzip ( String zipfile , String destDir ) {
            destDir = destDir.endsWith ( "//" ) ? destDir : destDir + "//";
            byte b[] = new byte[ 310 ];
            int length;
            try {
                  try ( ZipFile zipFile = new ZipFile ( new File ( zipfile ) ) ) {
                        Enumeration<?> enumeration = zipFile.entries ();
                        ZipEntry zipEntry;

                        while ( enumeration.hasMoreElements () ) {
                              zipEntry = ( ZipEntry ) enumeration.nextElement ();
                              File loadFile = new File ( destDir + zipEntry.getName () );

                              if ( zipEntry.isDirectory () ) {
                                    // 这段都可以不要，因为每次都貌似从最底层开始遍历的
                                    loadFile.mkdirs ();
                              } else {
                                    if (  ! loadFile.getParentFile ().exists () ) {
                                          loadFile.getParentFile ().mkdirs ();
                                    }
                                    InputStream inputStream;
                                    try ( OutputStream outputStream = new FileOutputStream ( loadFile ) ) {
                                          inputStream = zipFile.getInputStream ( zipEntry );
                                          while ( ( length = inputStream.read ( b ) ) > 0 ) {
                                                outputStream.write ( b , 0 , length );
                                          }
                                    }
                                    inputStream.close ();
                              }
                        }
                  }
            } catch ( IOException e ) {
            }
      }

      /**
       *
       * @param src
       * @param des
       */
      public static synchronized void unzip ( File src , File des ) {
            unzip ( src.getAbsolutePath () , des.getAbsolutePath () );
      }

      /**
       * 把一个文件由一个地方移动到另一个地方，移动方法是删除原文件
       */
      public static synchronized void move ( String from , String to ) {
            IO.move ( new File ( from ) , new File ( to ) );
      }

      /**
       *
       * @param from
       * @param to
       */
      public static synchronized void move ( File from , String to ) {
            IO.move ( from , new File ( to ) );
      }

      /**
       *
       * @param from
       * @param to
       */
      public static synchronized void move ( String from , File to ) {
            IO.move ( new File ( from ) , to );
      }

      /**
       *
       * @param from
       * @param to
       */
      public static synchronized void move ( File from , File to ) {
            IO.copy ( from , to );
            IO.del ( from );
      }

      /**
       *
       * @param from
       * @param to
       */
      public static synchronized void copy ( String from , String to ) {
            IO.copy ( new File ( from ) , new File ( to ) );
      }

      /**
       *
       * @param from
       * @param to
       */
      public static synchronized void copy ( String from , File to ) {
            IO.copy ( new File ( from ) , to );
      }

      /**
       *
       * @param from
       * @param to
       */
      public static synchronized void copy ( File from , String to ) {
            IO.copy ( from , new File ( to ) );
      }

      /**
       *
       * @param context
       * @param des
       */
      public static synchronized void save ( String context , String des ) {
            save ( context , new File ( des ) );
      }

      /**
       *
       * @param context
       * @param des
       */
      public static synchronized void save ( String context , File des ) {
            try {
                  if (  ! des.exists () ) {
                        File tmp = des.getParentFile ();
                        tmp.mkdirs ();
                        des.createNewFile ();
                  }
                  try ( FileOutputStream fos = new FileOutputStream ( des ) ) {
                        fos.write ( context.getBytes ( "utf8" ) );
                  }
            } catch ( FileNotFoundException ex ) {
                  System.out.println ( ex );
            } catch ( IOException ex ) {
                  System.out.println ( ex );
            }

      }

      /**
       * 将文件from复制到文件to
       *
       * @param from param to
       * @param to
       */
      public static synchronized void copy ( File from , File to ) {
            try {
                  if (  ! to.exists () ) {
                        File tmp = to.getParentFile ();
                        tmp.mkdirs ();
                        to.createNewFile ();
                  }
                  try ( FileOutputStream fos = null ; FileInputStream fis = new FileInputStream ( from ) ; FileChannel fcin = fis.getChannel () ) {
                        FileChannel fcout = fos.getChannel ();
                        Long size = from.length ();
                        MappedByteBuffer buffer = fcin.map ( MapMode.READ_ONLY , 0 , size );
                        fcout.write ( buffer );
                  }
            } catch ( FileNotFoundException ex ) {
                  System.out.println ( ex );
            } catch ( IOException ex ) {
                  System.out.println ( ex );
            }

      }

      /**
       *
       * @param file
       */
      public static synchronized void del ( String file ) {
            del ( new File ( file ) );
      }

      /**
       *
       * @param file
       */
      public static synchronized void del ( File file ) {
            if ( file.isDirectory () ) {
                  File[] files = file.listFiles ();
                  for ( File subFile : files ) {
                        if ( subFile.isDirectory () ) {
                              del ( subFile );
                        } else {
                              subFile.delete ();
                        }
                  }
            }
            file.delete ();
      }

      /**
       *
       * @param file1
       * @param file2
       * @return
       */
      public static synchronized Boolean equal ( File file1 , File file2 ) {
            //文件是否存在
            if (  ! file1.exists () ||  ! file2.exists () ) {
                  System.out.println ( "有文件不存在" );
                  return false;
            }
            //是否同一类型
            if ( file1.isDirectory () || file2.isDirectory () ) {
                  System.out.println ( "文件类型不一致" );
                  return false;
            }
            //检验扩展名
            if (  ! get ( file1 , 1 ).equalsIgnoreCase ( get ( file2 , 1 ) ) ) {
                  System.out.println ( "扩展名不一样" );
                  return false;
            }
            //检验大小
            if ( file1.length () != file2.length () ) {
                  System.out.println ( "文件大小不一样" );
                  return false;
            }
            //特征获取
            Long seed = System.currentTimeMillis ();
            Byte[] byte1 = diff ( file1 , seed );
            Byte[] byte2 = diff ( file2 , seed );
            if (  ! Arrays.equals ( byte1 , byte2 ) ) {
                  System.out.println ( "特征码不一致" );
                  return false;
            }
            return true;
      }

      /**
       *
       * @param file
       * @param seed
       * @return
       */
      public static synchronized Byte[] diff ( File file , Long seed ) {
            Random random = new Random ( seed );
            List<Byte> list = new ArrayList<> ( 111 );
            if ( file.isDirectory () ) {
                  Byte byt = Byte.decode ( "0" );
                  list.add ( byt );
                  return To.list2Array ( list );
            }
            try {
                  try ( RandomAccessFile raf = new RandomAccessFile ( file , "r" ) ) {
                        Long total = raf.length ();
                        Integer times = Roll.range ( total.intValue () , random );
                        for ( int x = 0 ; x < times ; x ++ ) {
                              list.add ( raf.readByte () );
                              raf.seek ( Roll.range ( times , random ) );
                        }
                  }
            } catch ( FileNotFoundException ex ) {
                  System.out.println ( ex );
            } catch ( IOException ex ) {
                  System.out.println ( ex );
            }
            return To.list2Array ( list );
      }

      /**
       *
       * @param file
       * @param part
       * @return
       */
      public static String get ( File file , Integer part ) {
            String name = file.getName ();
            if ( name.contains ( "." ) ) {
                  String[] tmp = name.split ( "\\." );
                  Integer len = tmp.length;
                  switch ( part ) {
                        case 0: {
                              len = 0;
                              break;
                        }
                        case 1: {
                              len -= 1;
                              break;
                        }
                        default: {
                              len -= 1;
                              break;
                        }
                  }
                  return tmp[len];
            } else {
                  return "";
            }
      }

      /**
       *
       * @param path
       * @param name
       * @return
       */
      public static File newFile ( File path , String name ) {
            String strPath = path.getPath () + "\\";
            return new File ( strPath + name );
      }

      /**
       *
       * @param image
       * @param path
       */
      public static synchronized void bufferedImage2Png ( BufferedImage image , String path ) {
            try {
                  FileOutputStream fileOutputStream = new FileOutputStream ( path );
                  ImageIO.write ( image , "PNG" , fileOutputStream );
            } catch ( FileNotFoundException ex ) {
                  System.err.println ( ex );
            } catch ( IOException ex ) {
                  System.err.println ( ex );
            }
      }

      public static synchronized void bufferedImage2PngC ( BufferedImage image ) {
            bufferedImage2Png ( image , "c:\\" + System.currentTimeMillis () + ".png" );
      }

      public static synchronized String file2String ( String path ) {
            StringBuffer stringBuffer = new StringBuffer ();
            try {
                  String readLine = null;
                  FileReader FileReader = new FileReader ( path );
                  try ( BufferedReader in = new BufferedReader ( FileReader ) ) {
                        while ( ( readLine = in.readLine () ) != null ) {
                              stringBuffer.append ( readLine );
                        }
                  }
            } catch ( IOException ex ) {
                  System.err.println ( ex );
            }
            return stringBuffer.toString ();
      }

      public static Properties readProperties ( File propertiesPath ) {
            Properties properties = new Properties ();
            try {
                  properties.load ( new FileInputStream ( propertiesPath ) );
            } catch ( Exception e ) {
                  System.err.println ( e );
            }
            return properties;
      }

      public static XML createXML ( String file ) {
            try {
                  return new XML ( file );
            } catch ( IOException ex ) {
                  ex.printStackTrace ();
                  return null;
            }
      }

}
